﻿
#include "MemBlock2.h"

int CMemBlock2::min2(int a, int b)
{
	if (a > b)
		return b;
	else
		return a;
}

CMemBlock2::CMemBlock2(void)
{
	memset(this, 0, sizeof(*this));

	m_pData = nullptr;
	m_iRdPtr = 0;		// 读串的起点
	m_iWdPtr = 0;

	m_iDataSize = MSG_BLOCK_SIZE;
	m_bInPool = true;

	bTimeOutPool = false;			// 有出池时间，若为零值表示在池内

	memset(m_szTextMark, 0, sizeof(m_szTextMark));
	m_sizeTextMark = 0;

	create();
}

CMemBlock2::CMemBlock2(char* pszTextMark, int iDataSize)
{
	m_pData = nullptr;
	m_iRdPtr = 0;		// 读串的起点
	m_iWdPtr = 0;

	m_iDataSize = iDataSize;
	m_bInPool = true;

	bTimeOutPool = false;	// 有出池时间，若为零值表示在池内

	int iTextLen = strlen(pszTextMark);

	memset(m_szTextMark, 0, sizeof(m_szTextMark));
	m_sizeTextMark = 0;

	if(pszTextMark && iTextLen>0)
	{
		m_sizeTextMark = min2(sizeof(m_szTextMark)-1, iTextLen);
		snprintf_safe(m_szTextMark, sizeof(m_szTextMark), pszTextMark, iTextLen);
	}

	create();
}

CMemBlock2::~CMemBlock2(void)
{
	release();
}

bool CMemBlock2::create()
{
	if( m_iDataSize <= 0 )
		return false;

	if(!m_pData)
	{
		m_pData = new char[m_iDataSize];
		memset(m_pData, 0, m_iDataSize);
	}

	if(m_pData)
		return true;

	return false;
}

bool CMemBlock2::release()
{
	if(m_pData)
	{
		delete[] m_pData;
		m_pData = nullptr;
	}

	if(!m_pData)
		return true;

	return false;
}

// 向消息块中考入内容
int CMemBlock2::copy(CMemBlock2* pMemBlock)
{
	if(!pMemBlock)
		return 10;

	return copy(pMemBlock->rd_ptr(), pMemBlock->length());
}

// 向消息块中考入内容
int CMemBlock2::copy(const char* pData, int iDataLen)
{
	//--- 安检 -------------
	if(!pData)
		return 10;

	if(iDataLen<=0)
		return 20;

	if(m_iDataSize - m_iWdPtr < iDataLen )
		return 30;

	//--- 考入内容 -----------

	int iWdPtrOld = m_iWdPtr;

	char* p = m_pData + m_iWdPtr;
	memcpy(p, pData, iDataLen);

	m_iWdPtr += iDataLen;
	
	#if 0
		// 测试用
		if(m_iWdPtr>=480)
		{
			printf("超限了 \n");
		}
	#endif

	return 0;
}

//// 向消息块中考入内容
//int CMemBlock2::copy(CMemBlock2* pMsgBlock)
//{
//	//--- 安检 -------------
//	if(!pMsgBlock)
//		return 10;
//
//	char* pData = pMsgBlock->rd_ptr();
//	int iDataLen = pMsgBlock->length();
//
//	if(iDataLen<=0)
//		return 20;
//
//	if(m_iDataSize - m_iWdPtr < iDataLen )	// 空间不足
//		return 30;
//
//	//--- 考入内容 -----------
//
//	int iWdPtrOld = m_iWdPtr;
//
//	char* p = m_pData + m_iWdPtr;
//	memcpy(p, pData, iDataLen);
//
//	m_iWdPtr += iDataLen;
//
//#if 0
//	// 测试用
//	if(m_iWdPtr>=480)
//	{
//		printf("超限了 \n");
//	}
//#endif
//
//	return 0;
//}

// 移动写指针
int CMemBlock2::write(int iLen,bool bEraseLeft)
{
	//--- 安检 -------------

	if(m_iDataSize < m_iWdPtr + iLen)
		return 10;

	//--- 考入内容 -----------

	int iWdPtrOld = m_iWdPtr;
	m_iWdPtr += iLen;

	// 如果要擦屁股
	// Cool.Cat
	if (bEraseLeft && iLen!=0)
	{
		// 屁股全部擦完。。。
		if (iLen>0)
			memset(m_pData+m_iWdPtr,0,space());
		// 只擦一部分~
		else
			memset(m_pData+m_iWdPtr,0,-iLen);
	}
	
	#if 0	// 测试用
		if(m_iWdPtr>=480)
		{
			printf("超限了 \n");
		}
	#endif

	return 0;
}

// 移动读指针
int CMemBlock2::rd_ptr(int iMove)
{
	int iTmp = iMove + m_iRdPtr;

	if(iTmp > m_iWdPtr)
		return 10;	// 超出写指针的长度了

	if(iTmp < 0)
		return 20;	// iMove 的负值过大

	m_iRdPtr += iMove;
	return 0;
}

// 获得读指针
char* CMemBlock2::rd_ptr()
{
	if(m_iRdPtr>=0 && m_iRdPtr<m_iDataSize)
		return &(m_pData[m_iRdPtr]);

	return nullptr;
}

// 将残余的内容移到头
int CMemBlock2::remains_move_to_head()
{
	if(0==m_iRdPtr)	// 读指针在最前端，不用移
		return 0;	

	int iInteval = m_iWdPtr - m_iRdPtr;

	if(iInteval>m_iDataSize)
		return 10;

	if(iInteval<=0)
		return 20;

	for(int i=0; i<iInteval; i++)
	{
		memcpy(&m_pData[i], &m_pData[i+m_iRdPtr], 1);
	}

	m_iRdPtr = 0;
	m_iWdPtr = iInteval;

	return 0;
}



// 获得文字标识，目的是在查询未释放的内存是知道是程序的哪一句申请的
void CMemBlock2::get_text_mark(char* pszTextMark, int iMaxLen)
{
	if(pszTextMark)
	{
		if(m_sizeTextMark>0)
		{
			sprintf(pszTextMark, "%s", m_szTextMark);
			pszTextMark[iMaxLen] = 0;
		}
	}
}

// 设置文字标识，目的是在查询未释放的内存是知道是程序的哪一句申请的
void CMemBlock2::set_text_mark(char* pszTextMark, int iTextLen)
{
	if(pszTextMark)
	{
		m_sizeTextMark = min2(sizeof(m_szTextMark)-1, iTextLen);

		snprintf_safe(m_szTextMark, sizeof(m_szTextMark), pszTextMark, iTextLen);

		m_szTextMark[m_sizeTextMark] = 0;
		m_szTextMark[TEXT_MARK_LEN-1] = 0;
	}
	else
	{
		memset(m_szTextMark, 0, sizeof(m_szTextMark));
		m_sizeTextMark = 0;
	}
}

// 清空文字标识，目的是在查询未释放的内存是知道是程序的哪一句申请的
void CMemBlock2::clear_text_mark()
{
	#if 1
		// 为了提高效率，不再对 m_szTextMark 整体清零，
		m_szTextMark[0] = 0;				// 第一位清零
		m_szTextMark[TEXT_MARK_LEN-1] = 0;	// 最后一位清零，以保证长度安全
	#else
		// 低效率
		memset(m_szTextMark, 0, sizeof(m_szTextMark));
	#endif

	m_sizeTextMark = 0;	// 仅改 m_sizeTextMark 值
}


// 安全的字符串拷贝
int CMemBlock2::snprintf_safe(char* szDst, int iDstSize, const char* szSrc, int iSrcLen)
{
#if WIN32
	if (iDstSize < iSrcLen + 1)
		assert(false);
#endif

	if (iDstSize <= iSrcLen + 1)
	{
		memcpy(szDst, szSrc, iDstSize);
		szDst[iDstSize - 1] = 0;   // 最后一个清成 0
		return iDstSize;
	}
	else
	{
		memcpy(szDst, szSrc, iSrcLen + 1);
		szDst[iSrcLen + 1] = 0;   // 最后一个清成 0
		return iSrcLen + 1;
	}
}

// 安全的字符串拷贝
int CMemBlock2::memcpy_safe(char* szDst, int iDstSize, const char* szSrc, int iSrcSize)
{
#if WIN32
	if (iDstSize < iSrcSize)
		assert(false);
#endif

	int iMin = 0;

	// 选出最小值
	if (iDstSize < iSrcSize)
		iMin = iDstSize;
	else
		iMin = iSrcSize;

	memcpy(szDst, szSrc, iMin);

	return iMin;
}